/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.meanzoft.m3d.texture;

import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import javax.imageio.ImageIO;

/**
 *
 * @author Meanz
 */
public class BLPLoader {

    public BLPLoader(String fileName) throws Exception {
        File file = new File(fileName);
        int i1 = (int) file.length();
        byte abyte0[] = new byte[i1];
        try {
            FileInputStream fileinputstream = new FileInputStream(fileName);
            fileinputstream.read(abyte0);
            fileinputstream.close();
        } catch (IOException ioexception) {
            throw new Exception("Error reading " + fileName);
        }
        ArrayReader arrayreader = new ArrayReader(abyte0);
        if (arrayreader.readByte() != 66 || arrayreader.readByte() != 76 || arrayreader.readByte() != 80 || arrayreader.readByte() != 50) {
            //throw new Exception(fileName + " is not a BLP2 file");
        }
        int j1 = arrayreader.readInt();
        int k1 = arrayreader.readByte();
        int l1 = arrayreader.readByte();
        int i2 = arrayreader.readByte();
        int j2 = arrayreader.readByte();
        imageWidth = arrayreader.readInt();
        imageHeight = arrayreader.readInt();
        mipmapOffsets = new int[16];
        for (int i = 0; i < 16; i++) {
            mipmapOffsets[i] = arrayreader.readInt();
        }

        mipmapLengths = new int[16];
        for (int j = 0; j < 16; j++) {
            mipmapLengths[j] = arrayreader.readInt();
        }

        if (k1 == 1) {
            if (i2 != 8) {
                throw new Exception("Indexed bitmaps with " + i2 + " bpp are not supported");
            }
        } else if (k1 == 2) {
            if (l1 != 0 && l1 != 8 && l1 != 1) {
                throw new Exception("DXT2 compressed images aren't supported yet");
            }
        } else {
            //throw new Exception("This type of bitmap compression (" + k1 + ") isn't supported yet");
        }
        if (j2 != 1 && j2 != 2 && j2 != 0) {
            throw new Exception("Critical Error: unknown4 = " + j2 + " dataformat = " + k1);
        }
        if (k1 == 1) {
            if (j2 == 0) {
                throw new Exception("Critical Error: dataFormat == 1 && unknown4 = " + j2);
            }
            arrayreader.seek(148);
            palette = arrayreader.readBytes(1024);
            if (l1 == 0) {
                bitmapType = 1;
                bitmapHasAlpha = false;
                arrayreader.seek(mipmapOffsets[0]);
                if (imageWidth * imageHeight != mipmapLengths[0]) {
                    throw new Exception("Critical Error: imageSize = " + imageWidth * imageHeight + ", mipmapSize = " + mipmapLengths[0]);
                }
                byte abyte1[] = arrayreader.readBytes(mipmapLengths[0]);
                bitmap = new int[imageWidth * imageHeight];
                for (int k = 0; k < imageWidth * imageHeight; k++) {
                    bitmap[k] = abyte1[k];
                }

            } else if (l1 == 8) {
                bitmapType = 1;
                bitmapHasAlpha = true;
                if (imageWidth * imageHeight * 2 != mipmapLengths[0]) {
                    throw new Exception("Critical Error: alpha imageSize = " + imageWidth * imageHeight + ", mipmapSize = " + mipmapLengths[0]);
                }
                arrayreader.seek(mipmapOffsets[0]);
                byte abyte2[] = arrayreader.readBytes(mipmapLengths[0] / 2);
                bitmap = new int[imageWidth * imageHeight];
                for (int l = 0; l < imageWidth * imageHeight; l++) {
                    bitmap[l] = abyte2[l];
                }

                arrayreader.seek(mipmapOffsets[0] + mipmapLengths[0] / 2);
                alphaChannel = arrayreader.readBytes(mipmapLengths[0] / 2);
            }
        } else if (k1 == 2) {
            if (l1 == 0 || l1 == 1) {
                if (j2 == 0) {
                    throw new Exception("Critical Error: dataFormat == 2 && unknown4 = " + j2);
                }
                bitmapType = 2;
                bitmapHasAlpha = false;
                arrayreader.seek(mipmapOffsets[0]);
                if ((imageWidth * imageHeight) / 2 != mipmapLengths[0]) {
                    throw new Exception("Critical Error: imageSize = " + imageWidth * imageHeight + ", mipmapSize = " + mipmapLengths[0] + ", maybe not DXT1");
                }
                byte abyte3[] = arrayreader.readBytes(mipmapLengths[0]);
                bitmap = DXTCFormat.decodeDXT1(imageWidth, imageHeight, abyte3);
            } else if (l1 == 8) {
                bitmapType = 2;
                bitmapHasAlpha = true;
                arrayreader.seek(mipmapOffsets[0]);
                if (imageWidth * imageHeight != mipmapLengths[0]) {
                    throw new Exception("Critical Error: imageSize = " + imageWidth * imageHeight + ", mipmapSize = " + mipmapLengths[0] + ", maybe not DXT1");
                }
                byte abyte4[] = arrayreader.readBytes(mipmapLengths[0]);
                bitmap = DXTCFormat.decodeDXT2(imageWidth, imageHeight, abyte4);
            }
        }
    }

    public void writePNG(String s) throws IOException, Exception {
        if (bitmapType == 1) {
            if (bitmapHasAlpha) {
                int i = -1;
                int j = -1;
                byte abyte2[] = new byte[256];
                byte abyte4[] = new byte[256];
                byte abyte5[] = new byte[256];
                for (int l = 0; l < 256; l++) {
                    abyte5[l] = palette[l * 4];
                    abyte4[l] = palette[l * 4 + 1];
                    abyte2[l] = palette[l * 4 + 2];
                }

                int ai[][] = new int[256][256];
                int i1 = 0;
                do {
                    if (i1 >= 256) {
                        break;
                    }
                    int k1 = i1 + 1;
                    do {
                        if (k1 >= 256) {
                            break;
                        }
                        if (abyte2[i1] - abyte2[k1] == 0 && abyte4[i1] - abyte4[k1] == 0 && abyte5[i1] - abyte5[k1] == 0) {
                            j = i1;
                            i = k1;
                            break;
                        }
                        i1++;
                    } while (true);
                    if (i != -1) {
                        break;
                    }
                    i1++;
                } while (true);
                if (i == -1) {
                    throw new Exception("Couldn't find transparency color");
                }
                IndexColorModel indexcolormodel1 = new IndexColorModel(8, 256, abyte2, abyte4, abyte5, i);
                for (int j1 = 0; j1 < imageWidth * imageHeight; j1++) {
                    if (bitmap[j1] == i) {
                        bitmap[j1] = j;
                    }
                    if (alphaChannel[j1] >= 0 && alphaChannel[j1] < 112) {
                        bitmap[j1] = i;
                    }
                }

                BufferedImage bufferedimage = new BufferedImage(imageWidth, imageHeight, 13, indexcolormodel1);
                WritableRaster writableraster3 = bufferedimage.getRaster();
                writableraster3.setPixels(0, 0, imageWidth, imageHeight, bitmap);
                File file3 = new File(s);
                ImageIO.write(bufferedimage, "png", file3);
            } else {
                byte abyte0[] = new byte[256];
                byte abyte1[] = new byte[256];
                byte abyte3[] = new byte[256];
                for (int k = 0; k < 256; k++) {
                    abyte3[k] = palette[k * 4];
                    abyte1[k] = palette[k * 4 + 1];
                    abyte0[k] = palette[k * 4 + 2];
                }

                IndexColorModel indexcolormodel = new IndexColorModel(8, 256, abyte0, abyte1, abyte3);
                BufferedImage bufferedimage1 = new BufferedImage(imageWidth, imageHeight, 13, indexcolormodel);
                WritableRaster writableraster2 = bufferedimage1.getRaster();
                writableraster2.setPixels(0, 0, imageWidth, imageHeight, bitmap);
                File file2 = new File(s);
                ImageIO.write(bufferedimage1, "png", file2);
            }
        } else if (bitmapType == 2) {
            if (bitmapHasAlpha) {
                BufferedImage bufferedimage2 = new BufferedImage(imageWidth, imageHeight, 2);
                WritableRaster writableraster = bufferedimage2.getRaster();
                writableraster.setPixels(0, 0, imageWidth, imageHeight, bitmap);
                File file = new File(s);
                ImageIO.write(bufferedimage2, "png", file);
            } else {
                BufferedImage bufferedimage3 = new BufferedImage(imageWidth, imageHeight, 1);
                WritableRaster writableraster1 = bufferedimage3.getRaster();
                writableraster1.setPixels(0, 0, imageWidth, imageHeight, bitmap);
                File file1 = new File(s);
                ImageIO.write(bufferedimage3, "png", file1);
            }
        }
    }

    public void writeBMP(String s)
            throws IOException {
        int i = imageWidth * imageHeight + 40 + 14 + 1024 + 2;
        ArrayWriter arraywriter = new ArrayWriter(i);
        arraywriter.writeByte(66);
        arraywriter.writeByte(77);
        arraywriter.writeInt(i);
        arraywriter.writeInt(0);
        arraywriter.writeInt(1078);
        arraywriter.writeInt(40);
        arraywriter.writeInt(imageWidth);
        arraywriter.writeInt(imageHeight);
        arraywriter.writeShort(1);
        arraywriter.writeShort(8);
        arraywriter.writeInt(0);
        arraywriter.writeInt(imageWidth * imageHeight + 2);
        arraywriter.writeInt(2834);
        arraywriter.writeInt(2834);
        arraywriter.writeInt(0);
        arraywriter.writeInt(0);
        arraywriter.writeBytes(palette);
        for (int j = 0; j < bitmap.length; j += imageWidth) {
            arraywriter.writeBytes(bitmap, bitmap.length - imageWidth - j, imageWidth);
        }

        arraywriter.writeShort(0);
        arraywriter.store(s);
    }

    private int[] getMipmap(int i) {
        if (i == 1) {
            return bitmap;
        }
        int j = imageWidth / i;
        int k = imageHeight / i;
        if (j == 0) {
            j = 1;
        }
        if (k == 0) {
            k = 1;
        }
        int ai[] = new int[j * k];
        for (int l = 0; l < k; l++) {
            for (int i1 = 0; i1 < j; i1++) {
                ai[l * j + i1] = bitmap[l * j * i + i1 * i];
            }

        }

        return ai;
    }

    private static int unsigned(byte byte0) {
        return byte0 < 0 ? 256 + byte0 : byte0;
    }
    int bitmapType;
    int imageWidth;
    int imageHeight;
    boolean bitmapHasAlpha;
    final int TYPE_PALETTE = 1;
    final int TYPE_RGB = 2;
    byte palette[];
    int bitmap[];
    byte alphaChannel[];
    int mipmapOffsets[];
    int mipmapLengths[];

    private static class DXTCFormat {

        public DXTCFormat() {
        }

        public static int[] decodeDXT1(int i, int j, byte abyte0[]) {
            int ai[] = new int[i * j * 3];
            int j2 = 0;
            int ai1[][] = new int[4][];
            for (int l = 0; l < j / 4; l++) {
                for (int k = 0; k < i / 4; k++) {
                    int k2 = unsigned(abyte0[j2]) + unsigned(abyte0[j2 + 1]) * 256;
                    int l2 = unsigned(abyte0[j2 + 2]) + unsigned(abyte0[j2 + 3]) * 256;
                    ai1[0] = decodeColor(k2);
                    ai1[1] = decodeColor(l2);
                    ai1[2] = new int[3];
                    ai1[3] = new int[3];
                    if (k2 > l2) {
                        for (int i1 = 0; i1 < 3; i1++) {
                            ai1[2][i1] = (2 * ai1[0][i1] + ai1[1][i1] + 1) / 3;
                        }

                        for (int j1 = 0; j1 < 3; j1++) {
                            ai1[3][j1] = (ai1[0][j1] + 2 * ai1[1][j1] + 1) / 3;
                        }

                    } else {
                        for (int k1 = 0; k1 < 3; k1++) {
                            ai1[2][k1] = (ai1[0][k1] + ai1[1][k1]) / 2;
                        }

                        ai1[3] = decodeColor(0);
                    }
                    for (int i2 = 0; i2 < 4; i2++) {
                        for (int l1 = 0; l1 < 4; l1++) {
                            int i3 = dxtcPixel(abyte0, j2 + 4, l1, i2);
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 3 + 0] = ai1[i3][0];
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 3 + 1] = ai1[i3][1];
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 3 + 2] = ai1[i3][2];
                        }

                    }

                    j2 += 8;
                }

            }

            return ai;
        }

        public static byte[] encodeDXT1(int i, int j, int ai[]) {
            byte abyte0[] = new byte[(i * j) / 2];
            int i3 = 0;
            int ai1[] = new int[3];
            int ai2[] = new int[3];
            int ai3[] = new int[3];
            int ai4[][] = new int[4][3];
            int ai5[][] = new int[16][3];
            for (int l = 0; l < j / 4; l++) {
                for (int k = 0; k < i / 4; k++) {
                    int j2 = 0;
                    int l2 = 0;
                    for (; j2 < 4; j2++) {
                        for (int i1 = 0; i1 < 4;) {
                            ai5[l2][0] = ai[((l * 4 + j2) * i + k * 4 + i1) * 3 + 0];
                            ai5[l2][1] = ai[((l * 4 + j2) * i + k * 4 + i1) * 3 + 1];
                            ai5[l2][2] = ai[((l * 4 + j2) * i + k * 4 + i1) * 3 + 2];
                            i1++;
                            l2++;
                        }

                    }

                    int k4 = 0;
                    int l4 = 0;
                    int i5 = 0;
                    for (int j1 = 0; j1 < 15; j1++) {
                        int j4 = furthestColor(ai5, j1);
                        int j5 = colorDistance(ai5[j1], ai5[j4]);
                        if (j5 > i5) {
                            i5 = j5;
                            k4 = j1;
                            l4 = j4;
                        }
                    }

                    System.arraycopy(ai5[k4], 0, ai4[0], 0, 3);
                    System.arraycopy(ai5[l4], 0, ai4[1], 0, 3);
                    int l3 = encodeColor(ai4[0]);
                    int i4 = encodeColor(ai4[1]);
                    if (l3 == i4) {
                        l3++;
                    } else if (l3 < i4) {
                        int k5 = l3;
                        l3 = i4;
                        i4 = k5;
                        System.arraycopy(ai4[0], 0, ai4[2], 0, 3);
                        System.arraycopy(ai4[1], 0, ai4[0], 0, 3);
                        System.arraycopy(ai4[2], 0, ai4[1], 0, 3);
                    }
                    for (int k1 = 0; k1 < 3; k1++) {
                        ai4[2][k1] = (2 * ai4[0][k1] + ai4[1][k1] + 1) / 3;
                    }

                    for (int l1 = 0; l1 < 3; l1++) {
                        ai4[3][l1] = (ai4[0][l1] + 2 * ai4[1][l1] + 1) / 3;
                    }

                    abyte0[i3] = (byte) (l3 % 256);
                    abyte0[i3 + 1] = (byte) (l3 / 256);
                    abyte0[i3 + 2] = (byte) (i4 % 256);
                    abyte0[i3 + 3] = (byte) (i4 / 256);
                    for (int k2 = 0; k2 < 4; k2++) {
                        int j3 = 0;
                        for (int i2 = 0; i2 < 4; i2++) {
                            int k3 = closestColor(ai4, ai5[k2 * 4 + i2]);
                            j3 += k3 << i2 * 2;
                        }

                        abyte0[i3 + 4 + k2] = (byte) j3;
                    }

                    i3 += 8;
                }

            }

            return abyte0;
        }

        public static byte[] encodeDXT2(int i, int j, int ai[]) {
            PrintStream printstream = null;
            try {
                printstream = new PrintStream(new FileOutputStream("debug.txt"));
            } catch (Exception exception) {
            }
            System.out.println("w = " + i + " h = " + j);
            System.out.println(ai.length);
            if (i < 4 || j < 4) {
                System.out.println("padding");
                int ai1[] = new int[64];
                for (int k = 0; k < 4; k++) {
                    for (int i1 = 0; i1 < 4; i1++) {
                        ai1[k * 4 + i1] = ai[((k * j) / 4) * 4 + (i1 * i) / 4];
                    }

                }

                ai = ai1;
                i = 4;
                j = 4;
            }
            byte abyte0[] = new byte[i * j];
            System.out.println("w = " + i + " h = " + j);
            int l3 = 0;
            int ai2[] = new int[3];
            int ai3[] = new int[3];
            int ai4[] = new int[3];
            int ai5[][] = new int[4][3];
            int ai6[][] = new int[16][3];
            int ai7[] = new int[16];
            for (int j1 = 0; j1 < j / 4; j1++) {
                for (int l = 0; l < i / 4; l++) {
                    int l2 = 0;
                    int k3 = 0;
                    for (; l2 < 4; l2++) {
                        for (int k1 = 0; k1 < 4;) {
                            ai6[k3][0] = ai[((j1 * 4 + l2) * i + l * 4 + k1) * 4 + 0];
                            ai6[k3][1] = ai[((j1 * 4 + l2) * i + l * 4 + k1) * 4 + 1];
                            ai6[k3][2] = ai[((j1 * 4 + l2) * i + l * 4 + k1) * 4 + 2];
                            ai7[k3] = ai[((j1 * 4 + l2) * i + l * 4 + k1) * 4 + 3];
                            k1++;
                            k3++;
                        }

                    }

                    int j5 = 0;
                    int k5 = 0;
                    int l5 = 0;
                    for (int l1 = 0; l1 < 15; l1++) {
                        int i5 = furthestColor(ai6, l1);
                        int i6 = colorDistance(ai6[l1], ai6[i5]);
                        if (i6 > l5) {
                            l5 = i6;
                            j5 = l1;
                            k5 = i5;
                        }
                    }

                    System.arraycopy(ai6[j5], 0, ai5[0], 0, 3);
                    System.arraycopy(ai6[k5], 0, ai5[1], 0, 3);
                    int k4 = encodeColor(ai5[0]);
                    int l4 = encodeColor(ai5[1]);
                    if (k4 == l4) {
                        if (k4 > 32768) {
                            l4 = 0;
                        } else {
                            l4 = 65535;
                        }
                        ai5[1] = decodeColor(l4);
                    } else if (k4 < l4) {
                        int j6 = k4;
                        k4 = l4;
                        l4 = j6;
                        System.arraycopy(ai5[0], 0, ai5[2], 0, 3);
                        System.arraycopy(ai5[1], 0, ai5[0], 0, 3);
                        System.arraycopy(ai5[2], 0, ai5[1], 0, 3);
                    }
                    for (int i2 = 0; i2 < 3; i2++) {
                        ai5[2][i2] = (2 * ai5[0][i2] + ai5[1][i2] + 1) / 3;
                    }

                    for (int j2 = 0; j2 < 3; j2++) {
                        ai5[3][j2] = (ai5[0][j2] + 2 * ai5[1][j2] + 1) / 3;
                    }

                    abyte0[l3 + 8] = (byte) (k4 % 256);
                    abyte0[l3 + 9] = (byte) (k4 / 256);
                    abyte0[l3 + 10] = (byte) (l4 % 256);
                    abyte0[l3 + 11] = (byte) (l4 / 256);
                    for (int i3 = 0; i3 < 4; i3++) {
                        int i4 = 0;
                        for (int k2 = 0; k2 < 4; k2++) {
                            int j4 = closestColor(ai5, ai6[i3 * 4 + k2]);
                            i4 += j4 << k2 * 2;
                        }

                        abyte0[l3 + 12 + i3] = (byte) i4;
                    }

                    for (int j3 = 0; j3 < 8; j3++) {
                        abyte0[l3 + j3] = (byte) ((ai7[j3 * 2 + 1] / 16 << 4) + ai7[j3 * 2] / 16);
                    }

                    l3 += 16;
                }

            }

            return abyte0;
        }

        public static int[] decodeDXT2(int i, int j, byte abyte0[]) {
            int ai[] = new int[i * j * 4];
            int j2 = 0;
            int ai1[][] = new int[4][];
            int ai2[] = new int[4];
            for (int l = 0; l < j / 4; l++) {
                for (int k = 0; k < i / 4; k++) {
                    for (int i1 = 0; i1 < 4; i1++) {
                        ai2[i1] = unsigned(abyte0[j2 + 2 * i1]) + unsigned(abyte0[j2 + 2 * i1 + 1]) * 256;
                    }

                    int l2 = unsigned(abyte0[j2 + 8]) + unsigned(abyte0[j2 + 9]) * 256;
                    int i3 = unsigned(abyte0[j2 + 10]) + unsigned(abyte0[j2 + 11]) * 256;
                    ai1[0] = decodeColor(l2);
                    ai1[1] = decodeColor(i3);
                    ai1[2] = new int[3];
                    ai1[3] = new int[3];
                    for (int j1 = 0; j1 < 3; j1++) {
                        ai1[2][j1] = (2 * ai1[0][j1] + ai1[1][j1] + 1) / 3;
                    }

                    for (int k1 = 0; k1 < 3; k1++) {
                        ai1[3][k1] = (ai1[0][k1] + 2 * ai1[1][k1] + 1) / 3;
                    }

                    for (int i2 = 0; i2 < 4; i2++) {
                        for (int l1 = 0; l1 < 4; l1++) {
                            int j3 = dxtcPixel(abyte0, j2 + 12, l1, i2);
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 4 + 0] = ai1[j3][0];
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 4 + 1] = ai1[j3][1];
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 4 + 2] = ai1[j3][2];
                            int k2 = dxtcAlpha(ai2, l1, i2);
                            ai[((l * 4 + i2) * i + k * 4 + l1) * 4 + 3] = k2 != 15 ? k2 * 16 : 255;
                        }

                    }

                    j2 += 16;
                }

            }

            return ai;
        }

        private static int furthestColor(int ai[][], int i) {
            int j = 0;
            int l = 0;
            for (int i1 = 0; i1 < ai.length; i1++) {
                if (i1 == i) {
                    continue;
                }
                int k = colorDistance(ai[i1], ai[i]);
                if (k > j) {
                    j = k;
                    l = i1;
                }
            }

            return l;
        }

        private static int closestColor(int ai[][], int ai1[]) {
            int i = 0;
            for (int j = 1; j < ai.length; j++) {
                if (colorDistance(ai1, ai[j]) < colorDistance(ai1, ai[i])) {
                    i = j;
                }
            }

            return i;
        }

        private static int colorDistance(int ai[], int ai1[]) {
            return (ai[0] - ai1[0]) * (ai[0] - ai1[0]) + (ai[1] - ai1[1]) * (ai[1] - ai1[1]) + (ai[2] - ai1[2]) * (ai[2] - ai1[2]);
        }

        private static int dxtcPixel(byte abyte0[], int i, int j, int k) {
            j *= 2;
            int l = unsigned(abyte0[i + k]);
            int i1 = (l & 3 << j) >> j;
            return i1;
        }

        private static int dxtcAlpha(int ai[], int i, int j) {
            i *= 4;
            int k = ai[j];
            int l = (k & 15 << i) >> i;
            return l;
        }

        private static int[] decodeColor(int i) {
            int j = i & 0x1f;
            int k = (i & 0x7e0) / 32;
            int l = (i & 0xf800) / 2048;
            int ai[] = new int[3];
            ai[0] = l * 8;
            ai[1] = k * 4;
            ai[2] = j * 8;
            return ai;
        }

        private static int encodeColor(int ai[]) {
            return ai[2] / 8 + (ai[1] / 4) * 32 + (ai[0] / 8) * 2048;
        }

        private static int unsigned(byte byte0) {
            return byte0 < 0 ? 256 + byte0 : byte0;
        }
    }

    public class ArrayWriter {

        public ArrayWriter(int i) {
            data = new byte[i];
            pos = 0;
        }

        public void seek(int i) {
            pos = i;
        }

        void writeInt(int i) {
            data[pos++] = (byte) (i & 0xff);
            data[pos++] = (byte) (i >> 8 & 0xff);
            data[pos++] = (byte) (i >> 16 & 0xff);
            data[pos++] = (byte) (i >> 24 & 0xff);
        }

        void writeShort(int i) {
            data[pos++] = (byte) (i & 0xff);
            data[pos++] = (byte) (i >> 8 & 0xff);
        }

        void writeByte(int i) {
            data[pos++] = (byte) (i & 0xff);
        }

        public void writeBytes(byte abyte0[]) {
            writeBytes(abyte0, 0, abyte0.length);
        }

        public void writeBytes(int ai[]) {
            writeBytes(ai, 0, ai.length);
        }

        public void writeBytes(byte abyte0[], int i, int j) {
            System.arraycopy(abyte0, i, data, pos, j);
            pos += j;
        }

        public void writeBytes(int ai[], int i, int j) {
            byte abyte0[] = new byte[j];
            for (int k = 0; k < j; k++) {
                abyte0[k] = (byte) ai[k];
            }

            writeBytes(abyte0, i, j);
        }

        public void store(String s)
                throws IOException {
            FileOutputStream fileoutputstream = new FileOutputStream(s);
            fileoutputstream.write(data);
            fileoutputstream.close();
        }
        private int pos;
        private byte data[];
    }

    public class ArrayReader {

        public ArrayReader(byte abyte0[]) {
            data = abyte0;
            pos = 0;
        }

        public void seek(int i) {
            pos = i;
        }

        public int readInt() {
            int i = 0;
            int j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j;
            j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j << 8;
            j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j << 16;
            j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j << 24;
            return i;
        }

        public int readShort() {
            int i = 0;
            int j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j;
            j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j << 8;
            return i;
        }

        public int readByte() {
            int i = 0;
            int j = data[pos++];
            if (j < 0) {
                j += 256;
            }
            i += j;
            return i;
        }

        public byte[] readBytes(int i) {
            byte abyte0[] = new byte[i];
            System.arraycopy(data, pos, abyte0, 0, i);
            pos += i;
            return abyte0;
        }
        private int pos;
        private byte data[];
    }
}